"""
作者: 临渊
日期: 2025/6/30
name: code版_康师傅畅饮社
入口: 微信小程序 (https://s.c1ns.cn/GekGz)
功能: 签到、查积分、每日C活动(签到、视频、邀请、小游戏)
变量: PROXY_API_URL (代理api，返回一条txt文本，内容为代理ip:端口)
    DEBUG_WXID (调试模式指定微信ID)
    yuanshen_api (过检软件API地址)
定时: 一天两次
# new Env("康师傅畅饮社")
# cron: 10 8,9 * * *
------------更新日志------------
2025/8/7   V2.8    修复昵称显示问题
"""

import random
import time
import requests
import os
import sys
import logging
import traceback
import ssl
import json
from datetime import datetime

MULTI_ACCOUNT_SPLIT = ["\n", "@"] # 分隔符列表
MULTI_ACCOUNT_PROXY = False # 是否使用多账号代理，默认不使用，True则使用多账号代理
NOTIFY = os.getenv("LY_NOTIFY") or False # 是否推送日志，默认不推送，True则推送
YUANSHEN_API = "http://" + os.getenv("yuanshen_api") if os.getenv("yuanshen_api") else None  # 过检软件API地址
TARGET_APP_ID = "wx54f3e6a00f7973a7"  # 目标小程序的APP_ID
DEBUG_WXID = os.getenv("DEBUG_WXID")  # 调试模式指定微信ID

# 请求头
REQUEST_HEADERS = {
    'Host': 'nclub.gdshcm.com',
    'Connection': 'keep-alive',
    'Content-Length': '72',
    'Token': '',  # 关键修改：使用Token头字段
    'charset': 'utf-8',
    'User-Agent': 'Mozilla/5.0 (Linux; Android 10; V1824A Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.103 Mobile Safari/537.36 XWEB/1300473 MMWEBSDK/20230805 MMWEBID/5374 MicroMessenger/8.0.42.2460(0x28002A35) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android',
    'content-type': 'application/json',
    'Referer': 'https://servicewechat.com/wx54f3e6a00f7973a7/226/page-frame.html',
    'Accept-Encoding': 'gzip,compress,br,deflate',
}

class TLSAdapter(requests.adapters.HTTPAdapter):
    """
    自定义TLS
    解决unsafe legacy renegotiation disabled
    """
    def init_poolmanager(self, *args, **kwargs):
        ctx = ssl.create_default_context()
        ctx.set_ciphers("DEFAULT@SECLEVEL=1")
        ctx.options |= 0x4   # <-- the key part here, OP_LEGACY_SERVER_CONNECT
        kwargs["ssl_context"] = ctx
        return super(TLSAdapter, self).init_poolmanager(*args, **kwargs)

class AutoTask:
    def __init__(self, script_name):
        """
        初始化自动任务类
        :param script_name: 脚本名称，用于日志显示
        """
        self.script_name = script_name
        self.wx_appid = TARGET_APP_ID # 微信小程序id
        self.proxy_url = os.getenv("PROXY_API_URL") # 代理api，返回一条txt文本，内容为代理ip:端口
        self.host = ""
        self.unionid = ""
        self.nickname = ""
        self.user_agent = "Mozilla/5.0 (Linux; Android 12; M2012K11AC Build/SKQ1.220303.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.136 Mobile Safari/537.36 XWEB/1340129 MMWEBSDK/20240301 MMWEBID/9871 MicroMessenger/8.0.48.2580(0x28003036) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android"
        self.ck_file = "康师傅畅饮社.json"  # CK存储文件名
        self.log_msgs = []  # 日志消息列表
        self.daily_c_invite_file = "daily_c_invite_unionid.txt"  # 每日C邀请unionid存储文件
        self.debug_mode = bool(DEBUG_WXID)  # 是否调试模式
        self.debug_wxid = DEBUG_WXID  # 调试指定的微信ID
        
    def log(self, msg, level="info"):
        """
        记录日志
        :param msg: 日志消息
        :param level: 日志级别
        """
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_msg = f"[{timestamp}] [{level.upper()}] {msg}"
        print(log_msg)
        self.log_msgs.append(log_msg)
        
        if level == "error":
            logging.error(log_msg)
        elif level == "warning":
            logging.warning(log_msg)
        else:
            logging.info(log_msg)

    def get_proxy(self):
        """
        获取代理
        :return: 代理
        """
        if not self.proxy_url:
            self.log("[获取代理] 没有找到环境变量PROXY_API_URL，不使用代理", level="warning")
            return None
        url = self.proxy_url
        response = requests.get(url)
        proxy = response.text
        self.log(f"[获取代理] {proxy}")
        return proxy

    def get_wx_list(self):
        """获取微信账户列表"""
        try:
            if not YUANSHEN_API:
                self.log("没有配置过检软件API地址(yuanshen_api)，无法获取微信账号列表", level="error")
                return []
                
            url = f"{YUANSHEN_API}/getallwx"
            response = requests.get(url, timeout=10)
            wx_list = response.json() if response.status_code == 200 else []
            
            # 调试模式：只保留指定的微信ID
            if self.debug_mode:
                wx_list = [acc for acc in wx_list if acc.get("Wxid") == self.debug_wxid]
                if wx_list:
                    self.log(f"调试模式：只处理微信ID {self.debug_wxid}", level="info")
                else:
                    self.log(f"调试模式：未找到微信ID {self.debug_wxid}", level="warning")
            
            return wx_list
        except Exception as e:
            self.log(f"获取微信列表失败: {str(e)}", level="error")
            return []

    def get_wx_code(self, wxid):
        """获取小程序登录凭证"""
        try:
            if not YUANSHEN_API:
                self.log("没有配置过检软件API地址(yuanshen_api)，无法获取微信code", level="error")
                return None
                
            url = f"{YUANSHEN_API}/loginbyapp?Wxid={wxid}&appid={self.wx_appid}"
            response = requests.get(url, timeout=10)
            if response.status_code == 200:
                return response.json().get("code")
            self.log(f"获取wxCode失败: HTTP {response.status_code}", level="error")
        except Exception as e:
            self.log(f"wxCode请求异常: {str(e)}", level="error")
        return None

    def get_ck(self, wx_code):
        """获取小程序登录凭证（CK）"""
        login_url = "https://nclub.gdshcm.com/pro/whale-member/api/login/login"
        payload = {
            "code": wx_code,
            "inviterId": "6816542043825766400",
            "inviterType": 1,
            "inviterMatchUserId": "",
            "spUrl": "null"
        }

        try:
            response = requests.post(
                login_url, 
                headers=REQUEST_HEADERS, 
                json=payload, 
                timeout=15
            )
            self.log(f"登录响应: {response.text}")
            
            # 修复登录响应解析
            if response.status_code == 200:
                try:
                    res_data = response.json()
                    # 检查是否有token字段
                    if res_data.get('code') == 0:
                        # 新版响应格式：token直接包含在data中
                        if isinstance(res_data.get('data'), str):
                            token = res_data['data']
                            member = {}
                        # 旧版响应格式：data是对象，包含token和member
                        elif isinstance(res_data.get('data'), dict):
                            token_data = res_data['data']
                            token = token_data.get('token')
                            member = token_data.get('member', {})
                        else:
                            token = None
                            member = {}
                        
                        if token:
                            # 获取用户信息
                            nickname = member.get('nickname', '未知用户')
                            unionid = member.get('unionid', '')
                            score = member.get('integral', 0)
                            self.log(f"[{nickname}] 登录成功, 积分: {score}")
                            
                            # 返回CK和UnionID - 关键修改：只返回纯token，不加Bearer前缀
                            return {
                                "ck": token,
                                "unionid": unionid,
                                "nickname": nickname
                            }
                        else:
                            self.log("❌ 响应中未找到token字段", level="warning")
                    else:
                        error_msg = res_data.get('msg', '未知错误')
                        self.log(f"❌ 登录失败: {error_msg}", level="error")
                except json.JSONDecodeError:
                    self.log(f"❌ 响应不是有效的JSON: {response.text}", level="error")
            else:
                self.log(f"❌ 请求失败: HTTP {response.status_code}, {response.text}", level="error")
        except Exception as e:
            self.log(f"❌ 登录异常: {e}", level="error")
        
        return None

    def validate_ck(self, ck):
        """验证 Bearer Token 的有效性"""
        url = "https://nclub.gdshcm.com/pro/whale-member/api/member/info"  
        headers = {
            'Host': 'nclub.gdshcm.com',
            'Connection': 'keep-alive',
            'User-Agent': self.user_agent,
            'content-type': 'application/json',
            'Referer': 'https://servicewechat.com/wx54f3e6a00f7973a7/226/page-frame.html',
            'Accept-Encoding': 'gzip,compress,br,deflate',
            # 关键修改：使用Token头字段
            'Token': ck
        }

        try:
            response = requests.get(url, headers=headers, timeout=10)
            if response.status_code == 200:
                try:
                    data = response.json()
                    if data.get("code") == 0:
                        self.log(f"✅ CK验证成功")
                        return True
                    else:
                        self.log(f"❌ CK验证失败: {data.get('msg', '未知错误')}", level="warning")
                except json.JSONDecodeError:
                    self.log(f"❌ CK验证响应不是JSON: {response.text[:200]}", level="warning")
            else:
                self.log(f"❌ CK验证失败: HTTP {response.status_code}", level="warning")
        except Exception as e:
            self.log(f"❌ CK验证请求出错: {e}", level="error")
        return False

    def load_ck_from_file(self):
        """从文件加载CK并验证有效性"""
        valid_results = []
        expired_accounts = []
        
        if not os.path.exists(self.ck_file):
            return valid_results, expired_accounts, set()
        
        try:
            with open(self.ck_file, "r") as f:
                ck_results = json.load(f)
                # 验证CK有效性
                for acc in ck_results:
                    # 调试模式：只处理指定微信ID
                    if self.debug_mode and acc.get("wxid") != self.debug_wxid:
                        continue
                        
                    if self.validate_ck(acc["ck"]):
                        valid_results.append(acc)
                    else:
                        self.log(f"❌ CK已失效: {acc.get('wxname', '未知账户')}", level="warning")
                        expired_accounts.append(acc)
        
            if valid_results:
                self.log(f"✅ 从文件加载 {len(valid_results)} 个有效CK")
            if expired_accounts:
                self.log(f"⚠️ 检测到 {len(expired_accounts)} 个失效CK", level="warning")
                
            # 返回现有wxid集合用于检测新账号
            existing_wxids = {acc["wxid"] for acc in ck_results}
            return valid_results, expired_accounts, existing_wxids
        except Exception as e:
            self.log(f"加载CK文件失败: {str(e)}", level="error")
            return [], [], set()

    def save_ck_to_file(self, ck_results):
        """保存CK到文件"""
        try:
            # 如果文件已存在，合并新旧数据
            existing_data = []
            if os.path.exists(self.ck_file):
                with open(self.ck_file, "r") as f:
                    existing_data = json.load(f)
            
            # 创建wxid到账号的映射
            account_map = {acc["wxid"]: acc for acc in existing_data}
            
            # 更新或添加新CK
            for new_acc in ck_results:
                account_map[new_acc["wxid"]] = new_acc
            
            merged_results = list(account_map.values())
            
            with open(self.ck_file, "w") as f:
                json.dump(merged_results, f, indent=2)
            self.log(f"💾 成功保存 {len(merged_results)} 个CK到 {self.ck_file}")
        except Exception as e:
            self.log(f"保存CK文件失败: {str(e)}", level="error")

    def fetch_ck(self, wx_accounts):
        """
        获取指定微信账号的CK
        :param wx_accounts: 需要获取CK的微信账号列表
        :return: 新获取的CK列表
        """
        if not wx_accounts:
            self.log("❌ 未提供微信账户列表", level="error")
            return []
        
        self.log(f"✅ 准备获取 {len(wx_accounts)} 个微信账户的CK")
        
        ck_results = []
        for account in wx_accounts:
            wxid = account.get("Wxid")
            wxname = account.get("wxname", "未知账户")  # 微信昵称
            
            # 调试模式：只处理指定微信ID
            if self.debug_mode and wxid != self.debug_wxid:
                continue
                
            # 使用微信昵称而不是微信ID
            self.log(f"\n🔍 处理账户: {wxname}")
            
            wx_code = self.get_wx_code(wxid)
            if not wx_code:
                self.log("❌ 获取wxCode失败")
                continue
            
            self.log(f"🔑 获取到wxCode: {wx_code[:8]}****")
            
            auth_data = self.get_ck(wx_code)
            if auth_data:
                ck = auth_data["ck"]
                unionid = auth_data["unionid"]
                # 使用微信昵称而不是登录返回的昵称
                nickname = wxname  
                
                self.log(f"🔐 获取CK成功: {ck[:23]}****")
                self.log(f"🔑 获取UnionID: {unionid[:6]}****")
                
                ck_results.append({
                    "wxid": wxid,
                    "wxname": nickname,  # 使用微信昵称
                    "ck": ck,
                    "unionid": unionid  # 保存UnionID
                })
            else:
                self.log("❌ 获取CK失败")
    
        if not ck_results:
            self.log("\n❌ 未获取到有效CK", level="warning")
            return []
        
        return ck_results

    def merge_ck_lists(self, original_list, new_list):
        """
        合并新旧CK列表
        :param original_list: 原始有效CK列表
        :param new_list: 新获取的CK列表
        :return: 合并后的CK列表
        """
        # 创建wxid到账号的映射
        account_map = {acc["wxid"]: acc for acc in original_list}
        
        # 更新或添加新CK
        for new_acc in new_list:
            account_map[new_acc["wxid"]] = new_acc
        
        return list(account_map.values())

    def detect_new_accounts(self, current_wx_list, existing_wxids):
        """
        检测新的微信账号
        :param current_wx_list: 当前微信账号列表
        :param existing_wxids: 已有CK中的wxid集合
        :return: 新账号列表
        """
        new_accounts = []
        for account in current_wx_list:
            wxid = account.get("Wxid")
            if wxid not in existing_wxids:
                new_accounts.append(account)
        
        return new_accounts

    def sign_in(self, session, ck):
        """
        签到
        :param session: session对象
        :param ck: 认证token
        :return: 签到结果
        """
        try:
            # 使用原脚本中的签到URL
            url = f"https://club.biqr.cn/api/signIn/integralSignIn"
            headers = {
                "Host": "club.biqr.cn",
                "Connection": "keep-alive",
                # 关键修改：使用Token头字段
                "Token": ck,
                "charset": "utf-8",
                "User-Agent": self.user_agent,
                "content-type": "application/json",
                "Referer": "https://servicewechat.com/wx54f3e6a00f7973a7/226/page-frame.html",
                "Accept-Encoding": "gzip,compress,br,deflate",
            }
            # 使用原脚本中的payload格式
            payload = "{}="
            
            response = session.post(url, headers=headers, data=payload, timeout=10)
            
            # 检查响应内容类型
            content_type = response.headers.get('Content-Type', '')
            if 'application/json' not in content_type:
                self.log(f"[{self.nickname}] 签到响应不是JSON格式: {content_type}", level="warning")
                self.log(f"响应内容: {response.text[:200]}", level="debug")
                return False
                
            try:
                response_json = response.json()
            except json.JSONDecodeError as e:
                self.log(f"[{self.nickname}] 签到响应JSON解析失败: {str(e)}", level="error")
                self.log(f"原始响应: {response.text[:500]}", level="debug")
                return False
                
            if int(response_json.get('code', 1)) == 0:
                self.log(f"[{self.nickname}] 签到成功")
                return True
            else:
                error_msg = response_json.get('msg', '未知错误')
                self.log(f"[{self.nickname}] 签到失败: {error_msg}", level="warning")
                return False
        except Exception as e:
            self.log(f"[{self.nickname}] 签到发生错误: {str(e)}\n{traceback.format_exc()}", level="error")
            return False

    def daily_c_signin(self, session, ck):
        """
        活动每日C 签到
        :param session: session对象
        :param ck: 认证token
        :return: 签到结果
        """
        try:
            url = f"https://ksfdailyc-api.teown.com/api/sign_in.php"
            headers = {
                "Host": "ksfdailyc-api.teown.com",
                "Connection": "keep-alive",
                # 关键修改：使用Token头字段
                "Token": ck,
                "charset": "utf-8",
                "User-Agent": self.user_agent,
                "content-type": "application/x-www-form-urlencoded",
                "Referer": "https://servicewechat.com/wx54f3e6a00f7973a7/226/page-frame.html",
                "Accept-Encoding": "gzip,compress,br,deflate",
            }
            payload = f"unionid={self.unionid}&timestamp={int(time.time())}"
            
            response = session.post(url, headers=headers, data=payload, timeout=5)
            
            # 检查响应内容类型
            content_type = response.headers.get('Content-Type', '')
            if 'application/json' not in content_type:
                self.log(f"[{self.nickname}] 每日C签到响应不是JSON格式: {content_type}", level="warning")
                self.log(f"响应内容: {response.text[:200]}", level="debug")
                return False
                
            try:
                response_json = response.json()
            except json.JSONDecodeError as e:
                self.log(f"[{self.nickname}] 每日C签到响应JSON解析失败: {str(e)}", level="error")
                self.log(f"原始响应: {response.text[:500]}", level="debug")
                return False
                
            if response_json.get('errcode') == 8000:
                score = response_json.get('data', {}).get('score', 0)
                self.log(f"[{self.nickname}] 每日C签到成功，获得{score}VC值")
                return True
            else:
                error_msg = response_json.get('errmsg', '未知错误')
                # 优化提示信息：将英文提示转换为中文
                if "has sign in" in error_msg.lower():
                    error_msg = "今日已签到"
                elif "not sign in" in error_msg.lower():
                    error_msg = "今日未签到"
                
                # 如果是已签到，降级为普通日志
                if "已签到" in error_msg:
                    self.log(f"[{self.nickname}] 每日C签到: {error_msg}")
                else:
                    self.log(f"[{self.nickname}] 每日C签到失败: {error_msg}", level="warning")
                return False
        except Exception as e:
            self.log(f"[{self.nickname}] 每日C签到发生错误: {str(e)}\n{traceback.format_exc()}", level="error")
            return False
        
    def daily_c_video(self, session, ck):
        """
        活动每日C 视频
        :param session: session对象
        :param ck: 认证token
        :return: 视频结果
        """
        try:
            url = f"https://ksfdailyc-api.teown.com/api/video.php"
            headers = {
                "Host": "ksfdailyc-api.teown.com",
                "Connection": "keep-alive",
                # 关键修改：使用Token头字段
                "Token": ck,
                "charset": "utf-8",
                "User-Agent": self.user_agent,
                "content-type": "application/x-www-form-urlencoded",
                "Referer": "https://servicewechat.com/wx54f3e6a00f7973a7/226/page-frame.html",
                "Accept-Encoding": "gzip,compress,br,deflate",
            }
            payload = f"unionid={self.unionid}&timestamp={int(time.time())}"
            
            # 添加随机延迟 (1-3秒)
            delay = random.uniform(1, 3)
            time.sleep(delay)
            
            response = session.post(url, headers=headers, data=payload, timeout=5)
            
            # 检查响应内容类型
            content_type = response.headers.get('Content-Type', '')
            if 'application/json' not in content_type:
                self.log(f"[{self.nickname}] 每日C视频响应不是JSON格式: {content_type}", level="warning")
                self.log(f"响应内容: {response.text[:200]}", level="debug")
                return False
                
            try:
                response_json = response.json()
            except json.JSONDecodeError as e:
                self.log(f"[{self.nickname}] 每日C视频响应JSON解析失败: {str(e)}", level="error")
                self.log(f"原始响应: {response.text[:500]}", level="debug")
                return False
                
            if response_json.get('errcode') == 8000:
                self.log(f"[{self.nickname}] 每日C视频请求成功")
                return True
            else:
                error_msg = response_json.get('errmsg', '未知错误')
                # 优化提示信息：将英文提示转换为中文
                if "has watched" in error_msg.lower():
                    error_msg = "今日已观看"
                elif "not watched" in error_msg.lower():
                    error_msg = "今日未观看"
                    
                self.log(f"[{self.nickname}] 每日C视频: {error_msg}")
                return False
        except Exception as e:
            self.log(f"[{self.nickname}] 每日C视频发生错误: {str(e)}\n{traceback.format_exc()}", level="error")
            return False
        
    def daily_c_mini_game(self, session, ck):
        """
        活动每日C 小游戏
        :param session: session对象
        :param ck: 认证token
        :return: 小游戏结果
        """
        try:
            url = f"https://club.biqr.cn/api/juiceGame/saveLog"
            headers = {
                "Host": "club.biqr.cn",
                "Connection": "keep-alive",
                # 关键修改：使用Token头字段
                "Token": ck,
                "charset": "utf-8",
                "User-Agent": self.user_agent,
                "content-type": "application/json",
                "Referer": "https://servicewechat.com/wx54f3e6a00f7973a7/226/page-frame.html",
                "Accept-Encoding": "gzip,compress,br,deflate",
            }
            payload = {
                "score": "u7Y2YshA2NFqWJIwDWXbZL%2BQ40o1WkNpiFnGzG1p73faQyVZ1BrGysG9U%2B%2BH7w2Zh%2Fmiz29ft3IqB%2F1EGN4O7GOz5CS5uTyIEhVxDOYJ5yhVel4KJaPApDRju%2FAmNy00Il%2BXlNsPkpJ%2F8PhZx0ov3HmPstIrwYPMnkdrDcwgnPY%3D"
            }
            
            # 添加随机延迟 (1-3秒)
            delay = random.uniform(1, 3)
            time.sleep(delay)
            
            response = session.post(url, headers=headers, json=payload, timeout=5)
            
            # 检查响应内容类型
            content_type = response.headers.get('Content-Type', '')
            if 'application/json' not in content_type:
                self.log(f"[{self.nickname}] 每日C小游戏响应不是JSON格式: {content_type}", level="warning")
                self.log(f"响应内容: {response.text[:200]}", level="debug")
                return False
                
            try:
                response_json = response.json()
            except json.JSONDecodeError as e:
                self.log(f"[{self.nickname}] 每日C小游戏响应JSON解析失败: {str(e)}", level="error")
                self.log(f"原始响应: {response.text[:500]}", level="debug")
                return False
                
            if int(response_json.get('code', 1)) == 0:
                self.log(f"[{self.nickname}] 每日C小游戏保存成绩成功")
                return True
            else:
                error_msg = response_json.get('msg', '未知错误')
                self.log(f"[{self.nickname}] 每日C小游戏: {error_msg}")
                return False
        except Exception as e:
            self.log(f"[{self.nickname}] 每日C小游戏发生错误: {str(e)}\n{traceback.format_exc()}", level="error")
            return False
        
    def daily_c_invite(self, session, ck, invite_unionid):
        """
        活动每日C 邀请/查信息
        :param session: session对象
        :param ck: 认证token
        :param invite_unionid: 邀请unionid
        :return: 邀请结果
        """
        try:
            url = f"https://ksfdailyc-api.teown.com/api/login.php"
            headers = {
                "Host": "ksfdailyc-api.teown.com",
                "Connection": "keep-alive",
                # 关键修改：使用Token头字段
                "Token": ck,
                "charset": "utf-8",
                "User-Agent": self.user_agent,
                "content-type": "application/x-www-form-urlencoded",
                "Referer": "https://servicewechat.com/wx54f3e6a00f7973a7/226/page-frame.html",
                "Accept-Encoding": "gzip,compress,br,deflate",
            }
            payload = f"unionid={invite_unionid}&refer={self.unionid}&timestamp={int(time.time())}"
            
            # 添加随机延迟 (1-3秒)
            delay = random.uniform(1, 3)
            time.sleep(delay)
            
            response = session.post(url, headers=headers, data=payload, timeout=5)
            
            # 检查响应内容类型
            content_type = response.headers.get('Content-Type', '')
            if 'application/json' not in content_type:
                self.log(f"[{self.nickname}] 每日C邀请响应不是JSON格式: {content_type}", level="warning")
                self.log(f"响应内容: {response.text[:200]}", level="debug")
                return False
                
            try:
                response_json = response.json()
            except json.JSONDecodeError as e:
                self.log(f"[{self.nickname}] 每日C邀请响应JSON解析失败: {str(e)}", level="error")
                self.log(f"原始响应: {response.text[:500]}", level="debug")
                return False
                
            if response_json.get('errcode') == 8000:
                if invite_unionid != self.unionid:
                    self.log(f"[{self.nickname}] 每日C邀请成功")
                else:
                    data = response_json.get('data', {})
                    sign_in = f"{data.get('sign_in_score', 0)}/{data.get('daily_sign_in_score', 0)}"
                    video = f"{data.get('video_score', 0)}/{data.get('daily_video_score', 0)}"
                    share = f"{data.get('share_score', 0)}/{data.get('daily_share_score', 0)}"
                    game = f"{data.get('game_score', 0)}/{data.get('daily_game_score', 0)}"
                    total_score = data.get('score', 0)
                    
                    self.log(f"[{self.nickname}] 每日C任务状态: 签到 {sign_in} 视频 {video} 分享 {share} 小游戏 {game}")
                    self.log(f"[{self.nickname}] 每日C总VC值: {total_score}")
                    return True
            else:
                error_msg = response_json.get('errmsg', '未知错误')
                # 优化提示信息：将英文提示转换为中文
                if "has invited" in error_msg.lower():
                    error_msg = "今日已邀请该用户"
                elif "not invited" in error_msg.lower():
                    error_msg = "今日未邀请该用户"
                    
                self.log(f"[{self.nickname}] 每日C邀请: {error_msg}")
                return False
        except Exception as e:
            self.log(f"[{self.nickname}] 每日C邀请发生错误: {str(e)}\n{traceback.format_exc()}", level="error")
            return False
        
    def daily_c_write_invite_unionid_list(self, unionid_list):
        """
        活动每日C 写入邀请unionid列表
        :param unionid_list: 邀请unionid列表
        """
        try:
            with open(self.daily_c_invite_file, "w", encoding="utf-8") as f:
                f.write("\n".join(unionid_list))
            self.log(f"每日C邀请列表已更新: {len(unionid_list)}个unionid")
        except Exception as e:
            self.log(f"每日C写入邀请unionid列表失败: {str(e)}", level="error")
            return False
            
    def daily_c_get_invite_unionid_list(self):
        """
        活动每日C 获取邀请unionid列表
        :return: 邀请unionid列表
        """
        try:
            # 检查是否存在文件
            if not os.path.exists(self.daily_c_invite_file):
                return []
            # 读取文件
            with open(self.daily_c_invite_file, "r", encoding="utf-8") as f:
                unionid_list = [line.strip() for line in f.readlines()]
            return unionid_list
        except Exception as e:
            self.log(f"每日C获取邀请unionid失败: {str(e)}", level="error")
            return []
    
    def run(self):
        """
        运行任务
        """
        try:
            self.log(f"【{self.script_name}】开始执行任务")
            if self.debug_mode:
                self.log(f"调试模式已启用，只处理微信ID: {self.debug_wxid}")
            
            # 第一步：尝试加载已有的CK并验证有效性
            valid_ck_list, expired_accounts, existing_wxids = self.load_ck_from_file()
            
            # 第二步：获取当前微信账户列表
            self.log("🔄 正在获取当前微信账户列表...")
            current_wx_list = self.get_wx_list()
            
            if not current_wx_list:
                self.log("❌ 未获取到任何微信账户，任务终止", level="error")
                return
                
            self.log(f"✅ 获取到 {len(current_wx_list)} 个微信账户")
            
            # 添加账号间初始延迟 (3-5秒)
            time.sleep(random.uniform(3, 5))
            
            # 第三步：检测新账号
            new_accounts = self.detect_new_accounts(current_wx_list, existing_wxids)
            if new_accounts:
                self.log(f"🎉 检测到 {len(new_accounts)} 个新账号:")
                for acc in new_accounts:
                    # 使用微信昵称而不是微信ID
                    self.log(f"  - {acc.get('wxname', '未知账号')}")
                
                # 获取新账号的CK
                new_ck_list = self.fetch_ck(new_accounts)
                if new_ck_list:
                    # 合并新账号到有效列表
                    merged_ck_list = self.merge_ck_lists(valid_ck_list, new_ck_list)
                    valid_ck_list = merged_ck_list
                    self.log(f"✅ 成功添加 {len(new_ck_list)} 个新账号的CK")
                else:
                    self.log("❌ 未能获取新账号的CK", level="warning")
            
            # 第四步：更新失效账号
            if expired_accounts:
                self.log("⚠️ 检测到失效CK，开始更新...", level="warning")
                # 构建需要更新的账号列表（仅限当前存在的账号）
                update_accounts = []
                for expired in expired_accounts:
                    # 查找当前微信列表中是否存在此wxid
                    for wx_acc in current_wx_list:
                        if wx_acc.get("Wxid") == expired["wxid"]:
                            update_accounts.append(wx_acc)
                            break
                
                if update_accounts:
                    updated_ck_list = self.fetch_ck(update_accounts)
                    if updated_ck_list:
                        # 合并更新后的CK
                        merged_ck_list = self.merge_ck_lists(valid_ck_list, updated_ck_list)
                        valid_ck_list = merged_ck_list
                        self.log(f"🔄 成功更新 {len(updated_ck_list)} 个失效账号的CK")
                    else:
                        self.log("❌ 未能更新失效账号的CK", level="error")
                else:
                    self.log("⚠️ 失效账号已不在当前微信列表中，跳过更新", level="warning")
            
            # 第五步：保存所有CK到文件
            if valid_ck_list:
                self.save_ck_to_file(valid_ck_list)
            else:
                # 如果没有有效CK，尝试获取所有账号的CK
                self.log("❌ 没有有效的CK，尝试获取所有账号的CK...", level="warning")
                all_ck_list = self.fetch_ck(current_wx_list)
                if all_ck_list:
                    self.save_ck_to_file(all_ck_list)
                    valid_ck_list = all_ck_list
                else:
                    self.log("❌ 未能获取任何CK，任务终止", level="error")
                    return
            
            # 第六步：执行任务
            if valid_ck_list:
                self.log(f"✅ 开始执行任务，共 {len(valid_ck_list)} 个账号")
                session = requests.Session()
                
                # 获取每日C邀请unionid列表
                invite_unionid_list = self.daily_c_get_invite_unionid_list()
                
                # 当前执行账号的unionid列表，用于更新邀请列表
                current_unionid_list = []
                
                for account in valid_ck_list:
                    try:
                        wxid = account["wxid"]
                        wxname = account["wxname"]  # 获取微信昵称
                        ck = account["ck"]
                        unionid = account.get("unionid", "")  # 从账号信息获取UnionID
                        
                        # 使用微信昵称而不是微信ID
                        self.log(f"\n------ 开始处理账号: {wxname} ------")
                        self.nickname = wxname  # 设置当前昵称为微信昵称
                        self.unionid = unionid  # 设置当前UnionID
                        
                        # 添加账号处理前延迟 (3-5秒)
                        time.sleep(random.uniform(3, 5))
                        
                        # 执行签到
                        self.sign_in(session, ck)
                        
                        # 如果还没有获取到unionid，尝试通过查询用户信息获取
                        if not self.unionid:
                            self.log(f"[{self.nickname}] 尚未获取到unionid，跳过每日C任务", level="warning")
                        else:
                            # 执行每日C活动任务
                            # 每日C签到
                            self.daily_c_signin(session, ck)
                            
                            # 每日C视频
                            self.daily_c_video(session, ck)
                            
                            # 每日C小游戏
                            self.daily_c_mini_game(session, ck)
                            
                            # 每日C邀请
                            if invite_unionid_list:
                                # 去除当前账号unionid
                                filtered_unionid_list = [uid for uid in invite_unionid_list if uid and uid != self.unionid]
                                
                                # 如果大于5个，随机取5个，否则直接全部
                                if len(filtered_unionid_list) > 5:
                                    filtered_unionid_list = random.sample(filtered_unionid_list, 5)
                                
                                # 邀请
                                for invite_unionid in filtered_unionid_list:
                                    self.daily_c_invite(session, ck, invite_unionid)
                                    # 邀请间延迟 (1-3秒)
                                    time.sleep(random.uniform(1, 3))
                            
                            # 查询自己账号信息（也作为邀请自己）
                            self.daily_c_invite(session, ck, self.unionid)
                            
                            # 将当前账号unionid加入列表
                            current_unionid_list.append(self.unionid)
                        
                        self.log(f"------ 账号处理完成 ------")
                        
                        # 账号间间隔 (5-8秒)
                        time.sleep(random.uniform(5, 8))
                        
                    except Exception as e:
                        self.log(f"处理账号 {wxname} 时出错: {str(e)}\n{traceback.format_exc()}", level="error")
                        continue
                
                # 更新每日C邀请unionid列表
                if current_unionid_list:
                    self.daily_c_write_invite_unionid_list(current_unionid_list)
            else:
                self.log("❌ 没有有效的CK可用，任务终止", level="error")
                
        except Exception as e:
            self.log(f"【{self.script_name}】执行过程中发生错误: {str(e)}\n{traceback.format_exc()}", level="error")
        finally:
            if NOTIFY:
                # 如果notify模块不存在，从远程下载至本地
                if not os.path.exists("notify.py"):
                    url = "https://raw.githubusercontent.com/whyour/qinglong/refs/heads/develop/sample/notify.py"
                    response = requests.get(url)
                    with open("notify.py", "w", encoding="utf-8") as f:
                        f.write(response.text)
                    import notify
                else:
                    import notify
                # 任务结束后推送日志
                title = f"{self.script_name} 运行日志"
                header = "作者：临渊\n"
                content = header + "\n" +"\n".join(self.log_msgs)
                notify.send(title, content)


if __name__ == "__main__":
    auto_task = AutoTask("康师傅畅饮社")
    auto_task.run()